Spring Security核心架构#
一句话答案#
Spring Security 基于 Servlet Filter Chain 实现,核心是 SecurityFilterChain 中的一系列 Filter(认证 UsernamePasswordAuthenticationFilter / JWT Filter + 授权 FilterSecurityInterceptor),通过 Authentication → SecurityContext 传递用户信息。
核心要点
架构分层#
HTTP 请求
↓
DelegatingFilterProxy (Servlet Filter → Spring Bean 桥接)
↓
FilterChainProxy (管理多个 SecurityFilterChain)
↓
SecurityFilterChain (按序执行 15+ 个 Security Filter)
├── SecurityContextPersistenceFilter (恢复/保存 SecurityContext)
├── UsernamePasswordAuthenticationFilter (表单登录)
├── BasicAuthenticationFilter (HTTP Basic)
├── BearerTokenAuthenticationFilter (JWT/OAuth2)
├── ExceptionTranslationFilter (异常转HTTP响应)
└── AuthorizationFilter (权限校验)
↓
Controllerplaintext认证流程#
1. 请求到达 AuthenticationFilter
2. Filter 从请求中提取凭证 → 构建未认证的 Authentication 对象
3. 交给 AuthenticationManager.authenticate()
4. AuthenticationManager 委托 AuthenticationProvider 验证
5. Provider 调用 UserDetailsService.loadUserByUsername() 加载用户
6. 比对密码(PasswordEncoder.matches())
7. 成功 → 构建已认证的 Authentication(含 Authorities)
8. 存入 SecurityContextHolder(ThreadLocal)
9. 后续请求从 SecurityContext 获取当前用户信息plaintext核心组件#
| 组件 | 职责 |
|---|---|
| SecurityFilterChain | Filter 链,处理请求的安全逻辑 |
| AuthenticationManager | 认证入口,委托 Provider |
| AuthenticationProvider | 实际认证逻辑(DB/LDAP/OAuth) |
| UserDetailsService | 加载用户信息 |
| PasswordEncoder | 密码加密/验证(BCrypt) |
| SecurityContextHolder | 存储当前用户(ThreadLocal) |
| GrantedAuthority | 权限标识(ROLE_ADMIN) |
自定义 JWT 认证#
@Component
public class JwtAuthFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain) {
String token = extractToken(request);
if (token != null && jwtUtil.validate(token)) {
Claims claims = jwtUtil.parse(token);
UsernamePasswordAuthenticationToken auth =
new UsernamePasswordAuthenticationToken(
claims.getSubject(), null, extractAuthorities(claims));
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.disable())
.sessionManagement(sm -> sm.sessionCreationPolicy(STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/register").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated())
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}
}java授权模型#
URL 级别: .requestMatchers("/admin/**").hasRole("ADMIN")
方法级别: @PreAuthorize("hasRole('ADMIN') and #userId == authentication.principal.id")
表达式: hasRole / hasAuthority / isAuthenticated / permitAllplaintext面试回答(2分钟版)
Spring Security 的核心是基于 Servlet Filter Chain 的安全过滤器链。请求到达后依次经过十几个 Security Filter,关键的几个:认证 Filter(如 JWT Filter)从请求中提取凭证,交给 AuthenticationManager → AuthenticationProvider → UserDetailsService 完成认证,成功后将 Authentication 对象存入 SecurityContextHolder(基于 ThreadLocal)。后续的授权 Filter 从 SecurityContext 取出当前用户的 Authorities,对比 URL 或方法上的权限配置做鉴权。自定义 JWT 认证就是写一个 OncePerRequestFilter:解析 Token → 验签 → 构建 Authentication → 存入 SecurityContext。授权支持 URL 级别(配置类中 requestMatchers)和方法级别(@PreAuthorize 注解)。和 Shiro 对比,Spring Security 更重但功能更全,和 Spring 生态集成更好,OAuth2/OIDC 开箱即用。
追问与易错
追问方向:
- “SecurityContext 怎么跨线程?”→ 默认 ThreadLocal 不跨线程,异步需要 DelegatingSecurityContextExecutor
- “怎么自定义认证逻辑?”→ 实现 AuthenticationProvider + UserDetailsService
- “和 Shiro 比有什么优势?”→ Spring 生态集成好,OAuth2 支持完善,社区活跃
- “CSRF 为什么用 JWT 时可以关?”→ JWT 不依赖 Cookie 自动发送,CSRF 攻击不生效
易错点:
- ❌ “Spring Security 只能用 Session”——可以配置 STATELESS 纯 JWT 模式
- ❌ “Filter 顺序不重要”——顺序严格固定,自定义 Filter 用 addFilterBefore/After 指定位置
- ❌ “hasRole 和 hasAuthority 一样”——hasRole 会自动加 ROLE_ 前缀